const postcss = require('postcss');
const sizeOf = require('image-size');
const config = require('../upload/config');
const fs = require("fs");
const path = require('path');
module.exports = () => {
  const assetsDecl = {};
  ([
    'background', 'mask',
  ]).forEach(name=>{
    assetsDecl[name] = parseDecl;
  });
  function checkStyle(rule,type){
    const size = {
      width:[0,'px'],
      height:[0,'px'],
    };
    const setStyle = new Set([
      'width','height',
    ]);
    rule.walkDecls(/^(left|top)/, decl => {
      if(decl.prop === 'left'&&decl.value.indexOf('%')>0){
        setStyle.add('margin-left');
      }else if(decl.prop === 'top'&&decl.value.indexOf('%')>0){
        setStyle.add('margin-top');
      }
    })
    switch(type){
      case 'background':{
        setStyle.add('background-size');
        setStyle.add('background-repeat');
        break;
      }
      case 'mask':{
        setStyle.add('mask-size');
        setStyle.add('mask-repeat');
        break;
      }
    }
    rule.walkDecls(/^(width|height|margin|background-size|background-repeat|mask-repeat|mask-size)/, decl => {
      if(decl.prop === 'width'||decl.prop === 'height'){
        setStyle.delete(decl.prop);
        size[decl.prop] = [+decl.value.replace(/[^\d\.]+$/,''),decl.value.replace(/^[\d\.]+/,'')];
      }else if(decl.prop === 'margin'){
        setStyle.delete('margin-left');
        setStyle.delete('margin-top');
      }else if(decl.prop === 'margin-left'||decl.prop === 'margin-top'){
        setStyle.delete(decl.prop);
      }else if(decl.prop === 'background-size'||decl.prop === 'background-repeat'){
        let nextNode = decl.next();
        while(nextNode){
          if(nextNode.prop==='background') break;
          else{
            nextNode = nextNode.next();
          }
        }
        if(!nextNode) setStyle.delete(decl.prop);
      }else if(decl.prop === 'mask-size'||decl.prop === 'mask-repeat'){
        let nextNode = decl.next();
        while(nextNode){
          if(nextNode.prop==='mask') break;
          else{
            nextNode = nextNode.next();
          }
        }
        if(!nextNode) setStyle.delete(decl.prop);
      }
    })
    return {
      setStyle,
      ...size
    };
  }
  function parseDecl(decl){
    if(decl.value.search(/(?:url|inline)\([^\)]/)>=0){
      const {setStyle,width:cacheWidth,height:cacheHeight} = checkStyle(decl.parent,decl.prop);
      const sizeName = `${decl.prop}-size`;
      const repeatName = `${decl.prop}-repeat`;
      let sizeDecl;
      if(setStyle.has(sizeName)){
        // sizeDecl = postcss.decl({ prop: sizeName, value: 'contain' });
        sizeDecl = postcss.decl({ prop: sizeName, value: '100% 100%' });//contain 不如 100% 100% 好用
        decl.after(sizeDecl);
        setStyle.delete(sizeName);
      }
      const valueList = decl.value.split(/ +/);
      const rawValueList = decl.source.input.css.substring(decl.source.start.offset,decl.source.end.offset).split(/\s*\:\s*/)[1].split(/ +/);
      let hasRepeat = false;
      let rawURL = '';
      const imageConfig = {};
      for(let i = 0; i< valueList.length; i++){
        const value = rawValueList[i];
        if(value&&value.search(/(?:url|inline)\(/)>=0){
          rawURL = value.match(/(?:url|inline)\(([^\)]+)/)[1].replace(/(^[\'\"]|[\'\"]$)/g,'');
          if(rawURL.indexOf('#')>=0){
            rawValueList[i] = rawValueList[i].replace(/\#[^?\'\"\)]*/,'');
            const match = rawURL.match(/#([^\?]*)/)[1];
            if(match){
              match.replace(/[a-z]/ig,(char,index)=>{
                if(index){
                  return `&${char}`;
                }
                return char;
              }).split('&').forEach(item=>{
                imageConfig[item[0]] = +item.substr(1);
              });
            }
          }
        }else if(valueList[i].indexOf('repeat')>=0){
          hasRepeat = true;
        }
      }
      if(!hasRepeat&&setStyle.has(repeatName)) valueList.push('no-repeat');
      setStyle.delete(repeatName);
      decl.value = valueList.join(' ');
      if(imageConfig.x!==undefined||imageConfig.y!==undefined){
        let x = (imageConfig.x===undefined?1:imageConfig.x)*100;
        let y = (imageConfig.y===undefined?1:imageConfig.y)*100;
        if(sizeDecl) sizeDecl.value = `${x}% ${y}%`;
      }
      if(rawURL){
        if(setStyle.size){
          const scale = imageConfig.s===undefined?1:imageConfig.s;
          let fileURL = rawURL.replace(/[\?\#].*$/,'').replace(/\\/,'/');
          let dimensions;
          if(!/^((https?\:)?\/\/|data\:)/.test(fileURL)){
            if(path.isAbsolute(fileURL)){
              let _fileURL = path.join(config.projectPath,`.${fileURL}`);
              if(!fs.existsSync(fileURL)){
                _fileURL = path.join(config.projectPath,`./public/${fileURL}`);
              }
              fileURL = _fileURL;
            }else{
              fileURL = path.join(decl.source.input.file,'..',fileURL);
            }
            if(fs.existsSync(fileURL)){
              dimensions = sizeOf(fileURL);
            }
          }
          if(dimensions){
            if(imageConfig.x!==undefined){
              dimensions.width/=imageConfig.x;
            }
            if(imageConfig.y!==undefined){
              dimensions.height/=imageConfig.y;
            }
            setStyle.has('width')&&decl.before(postcss.decl({ prop: 'width', value: `${dimensions.width*scale}px` }));
            setStyle.has('height')&&decl.before(postcss.decl({ prop: 'height', value: `${dimensions.height*scale}px` }));
            setStyle.has('margin-left')&&decl.before(postcss.decl({ prop: 'margin-left', value: `${-dimensions.width*scale/2}px` }));
            setStyle.has('margin-top')&&decl.before(postcss.decl({ prop: 'margin-top', value: `${-dimensions.height*scale/2}px` }));
          }
        }
      }
    }
  }
  return {
      postcssPlugin: 'postcss-autoAssetsSize',
      Declaration:{
        ...assetsDecl
      }
  }
};
module.exports.postcss = true;